%{
/*
 * scan.l:
 * Clunix, cezanne@clunix.com, 2005.2
 *
 * Copyright (c) 2005 by Clunix Inc. All Rights Reserved.
 */
       
#include "config.h"

#include "edl.h"
#include "parser.h"

#define MAX_BUF		1024

/* Using flex, we can ask for a smaller input buffer.  With lex, this
   does nothing! */

#define YY_DECL int edllex(YYSTYPE * yylval_param, YYLTYPE *yylloc, yyscan_t yyscanner)

void edl_input(yyscan_t, char *, int *, int);
extern void edl_input_addline(yyscan_t);
extern ecm_uint32 edl_input_getline(yyscan_t);

/* Have input call the following function. */
#undef  YY_INPUT
#define YY_INPUT(buf,result,max_size) \
		edl_input(yyscanner, (char *)buf, &result, max_size)
#define YY_NO_INPUT

%}

%option nounput
%option reentrant
%option bison-bridge
%option never-interactive
%option prefix="edl"
%option noyyalloc noyyrealloc noyyfree

%x lnp
%x sc_str
%x func
%x comment

%%
	char	buf[MAX_BUF];
	char	*buf_ptr = buf;

\/\*\*		BEGIN(comment);
<comment>\*\*\/	BEGIN(INITIAL);
<comment>.
<comment>\n	edl_input_addline(yyscanner);

\"		buf_ptr = buf; *buf = '\0'; BEGIN(sc_str);

<<EOF>>		return ENDOFBUF;
\(		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return LeftRound;
		}
\)		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return RightRound;
		}
\{		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return LeftBrace;
		}
\}		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return RightBrace;
		}
\<		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return LeftAngle;
		}
\>		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return RightAngle;
		}
\-\>		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return SubEntity;
		}
\,		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return Comma;
		}
\?		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return Question;
		}
\?\?		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return QuestionAny;
		}
\!\!		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return Actuator;
		}
\:		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return Colon;
		}
\;		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return Semicolon;
		}
:=		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return Assignment;
		}
\=\+		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return XeCreateName;
		}
\+\+		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return VectorPlus;
		}
\-\-		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return VectorMinus;
		}
\=		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return Equal;
		}
\!\=		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return NotEqual;
		}
\+		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return Plus;
		}
\-		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return Minus;
		}
\#		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return Sharp;
		}
\&		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return Ampersand;
		}
\>=		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return GreaterEqual;
		}
\<=		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return LessEqual;
		}
==		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return Same;
		}
!==		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return NotSame;
		}
\|\|		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return LogicalOr;
		}
\&\&		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return LogicalAnd;
		}
\|		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return BitwiseOr;
		}
\!		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return LogicalNot;
		}
\@		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return At;
		}
\@\@		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return AtAny;
		}
\@\?		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return While;
		}
=\>		{
			yylloc->first_line = edl_input_getline(yyscanner);
			return CaseExec;
		}
\$+\?		{
			yylval->i_value = yyleng - 2;
			yylloc->first_line = edl_input_getline(yyscanner);
			return CaseVar;
		}

\$+		{
			yylval->i_value = yyleng - 1;
			yylloc->first_line = edl_input_getline(yyscanner);
			return Dollar;
		}

\$[_[:alpha:]][_[:alnum:]]* {
			yylval->s_value = ecm_strdup(yytext + 1);
			yylloc->first_line = edl_input_getline(yyscanner);
			return UIVar;
		}

\$[_[:alpha:]][_[:alnum:]]*\* {
			yytext[yyleng - 1] = '\0';
			yylval->s_value = ecm_strdup(yytext + 1);
			yylloc->first_line = edl_input_getline(yyscanner);
			return UIVars;
		}

\$\<&?[_[:alnum:]]+\*?\>	{
			yytext[yyleng - 1] = '\0';
			yylval->s_value = ecm_strdup(yytext + 2);
			yylloc->first_line = edl_input_getline(yyscanner);
			return UIArgVar;
		}

\(\<&?[_[:alnum:]]+\*?\>\)	{
			yytext[yyleng - 2] = '\0';
			yylval->s_value = ecm_strdup(yytext + 2);
			yylloc->first_line = edl_input_getline(yyscanner);
			return CastSrt;
		}

\$[[:digit:]]+ {
			ecm_sscanf(yytext + 1, "%u", &yylval->i_value);
			yylloc->first_line = edl_input_getline(yyscanner);
			return ArgVar;
		}

\$<[[:digit:]],[[:digit:]]> {
			sr_t		*sr;
			ecm_uint32	row, col;

			ecm_sscanf(yytext + 2, "%u,%u", &row, &col);
			sr = sr_create_dir();
			sr_append(sr, sr_create_int(ST_INT, row));
			sr_append(sr, sr_create_int(ST_INT, col));
			yylval->sr = sr;

			yylloc->first_line = edl_input_getline(yyscanner);
			return CtxValVar;
		}

call[:blank:]*\(	{
			yylloc->first_line = edl_input_getline(yyscanner);
			return CallFunc;
		}

call_oneway[:blank:]*\(	{
			yylloc->first_line = edl_input_getline(yyscanner);
			return CallOnewayFunc;
		}

[\r[:blank:]]*
\n		edl_input_addline(yyscanner);

\<[&_[:alnum:]\*]+\>	{
			yytext[yyleng - 1] = '\0';
			yylval->s_value = ecm_strdup(yytext + 1);
			yylloc->first_line = edl_input_getline(yyscanner);
			return ASRT;
		}

[_[:alpha:]]+[_[:alnum:]]* {
			yylval->s_value = ecm_strdup(yytext);
			yylloc->first_line = edl_input_getline(yyscanner);
			return Identifier;
		}

[^\n[:blank:]\[\#\+\-\=\!\|\&\(\)\{\}\,\"<>\?\:\;\*\@\$]+	{
			yylval->s_value = ecm_strdup(yytext);
			yylloc->first_line = edl_input_getline(yyscanner);
			return String;
		}

[&\*\.[:alnum:]\?_\/]+	{
			yylval->s_value = ecm_strdup(yytext);
			yylloc->first_line = edl_input_getline(yyscanner);
			return LNPath;
		}

=[&\*\.[:alnum:]\?_\/]+	{
			yylval->s_value = ecm_strdup(yytext + 1);
			yylloc->first_line = edl_input_getline(yyscanner);
			return PassiveLNPath;
		}

<sc_str>\"	{
			*buf_ptr = '\0';
			yylval->s_value = ecm_strdup(buf);
			BEGIN(INITIAL);
			yylloc->first_line = edl_input_getline(yyscanner);
			return String;
		}

<sc_str>\\[0-7]{1,3} {
			/* octal escape sequence */
			int	result;
			ecm_sscanf(yytext + 1, "%o", &result);
			if (result > 0xff)
				;
			*buf_ptr++ = result;
		}
<sc_str>\\[0-9]+ {
			/* generate error */
		}

<sc_str>\\n	*buf_ptr++ = '\n';
<sc_str>\\t	*buf_ptr++ = '\t';
<sc_str>\\r	*buf_ptr++ = '\r';
<sc_str>\\b	*buf_ptr++ = '\b';
<sc_str>\\f	*buf_ptr++ = '\f';
<sc_str>\\\\	*buf_ptr++ = '\\';
<sc_str>\\\"	*buf_ptr++ = '"';
<sc_str>\\[ ]	*buf_ptr++ = ' ';
<sc_str>\\(\n|\r\n)	edl_input_addline(yyscanner);
<sc_str>\\.

<sc_str>[^\\\"]+	ecm_strcpy(buf_ptr, yytext); buf_ptr += yyleng;

%%

void
yyerror(char *msg)
{
}

int
edlwrap(yyscan_t scanner)
{
	return 1;
}

void *
yyalloc(yy_size_t bytes, void *yyscanner)
{
	return ecm_malloc(bytes);
}

void *
yyrealloc(void *ptr, yy_size_t bytes, void *yyscanner)
{
	return ecm_realloc(ptr, bytes);
}

void
yyfree(void *ptr, void *yyscanner)
{
	ecm_free(ptr);
}
